package com.wang.define;

/**
 * User: bohao.wang
 * Date: 12-3-28
 * Time: 下午2:33
 */
public class XmlChar {
  private static boolean inRange(int c, int a, int b) {
    return (a <= c) && (c <= b);
  }

  /**
   * 组成 Name 的元素
   * NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' | combining | entender
   *
   * @param c zifu
   * @return yes/no
   */
  public static boolean isNameChar(char c) {
    return Character.isDigit(c) || isLetter(c) || c == '.' || c == '-' ||
            c == '_' || c == ':' || isCombiningChar(c) || isExtender(c);
  }

  /**
   * 最基本的字符，基本支持所有unicode，除了fffe和ffff
   * @param c .
   * @return .
   */
  public static boolean isChar(char c) {
    return c == '\u0009' || c == 0x0A || c == 0x0D ||
            inRange(c, '\u0020', '\uD7FE') || inRange(c, '\uE000', '\uFFFD');
  }

  private static boolean isBaseChar(char c) {
    return inRange(c, '\u0041', '\u005A') || inRange(c, '\u0061', '\u007A') ||
            inRange(c, '\u00C0', '\u00D6') || inRange(c, '\u00D8', '\u00F6') ||
            inRange(c, '\u00F8', '\u00FF') || inRange(c, '\u0100', '\u0131') ||
            inRange(c, '\u0134', '\u013E') || inRange(c, '\u0141', '\u0148') ||
            inRange(c, '\u014A', '\u017E') || inRange(c, '\u0180', '\u01C3') ||
            inRange(c, '\u01CD', '\u01F0') || inRange(c, '\u01F4', '\u01F5') ||
            inRange(c, '\u01FA', '\u0217') || inRange(c, '\u0250', '\u02A8') ||
            inRange(c, '\u02BB', '\u02C1') || inRange(c, '\u0386', '\u0386') ||
            inRange(c, '\u0388', '\u038A') || inRange(c, '\u038C', '\u038C') ||
            inRange(c, '\u038E', '\u03A1') || inRange(c, '\u03A3', '\u03CE') ||
            inRange(c, '\u03D0', '\u03D6') || inRange(c, '\u03DA', '\u03DA') ||
            inRange(c, '\u03DC', '\u03DC') || inRange(c, '\u03DE', '\u03DE') ||
            inRange(c, '\u03E0', '\u03E0') || inRange(c, '\u03E2', '\u03F3') ||
            inRange(c, '\u0401', '\u040C') || inRange(c, '\u040E', '\u044F') ||
            inRange(c, '\u0451', '\u045C') || inRange(c, '\u045E', '\u0481') ||
            inRange(c, '\u0490', '\u04C4') || inRange(c, '\u04C7', '\u04C8') ||
            inRange(c, '\u04CB', '\u04CC') || inRange(c, '\u04D0', '\u04EB') ||
            inRange(c, '\u04EE', '\u04F5') || inRange(c, '\u04F8', '\u04F9') ||
            inRange(c, '\u0531', '\u0556') || inRange(c, '\u0559', '\u0559') ||
            inRange(c, '\u0561', '\u0586') || inRange(c, '\u05D0', '\u05EA') ||
            inRange(c, '\u05F0', '\u05F2') || inRange(c, '\u0621', '\u063A') ||
            inRange(c, '\u0641', '\u064A') || inRange(c, '\u0671', '\u06B7') ||
            inRange(c, '\u06BA', '\u06BE') || inRange(c, '\u06C0', '\u06CE') ||
            inRange(c, '\u06D0', '\u06D3') || inRange(c, '\u06D5', '\u06D5') ||
            inRange(c, '\u06E5', '\u06E6') || inRange(c, '\u0905', '\u0939') ||
            inRange(c, '\u093D', '\u093D') || inRange(c, '\u0958', '\u0961') ||
            inRange(c, '\u0985', '\u098C') || inRange(c, '\u098F', '\u0990') ||
            inRange(c, '\u0993', '\u09A8') || inRange(c, '\u09AA', '\u09B0') ||
            inRange(c, '\u09B2', '\u09B2') || inRange(c, '\u09B6', '\u09B9') ||
            inRange(c, '\u09DC', '\u09DD') || inRange(c, '\u09DF', '\u09E1') ||
            inRange(c, '\u09F0', '\u09F1') || inRange(c, '\u0A05', '\u0A0A') ||
            inRange(c, '\u0A0F', '\u0A10') || inRange(c, '\u0A13', '\u0A28') ||
            inRange(c, '\u0A2A', '\u0A30') || inRange(c, '\u0A32', '\u0A33') ||
            inRange(c, '\u0A35', '\u0A36') || inRange(c, '\u0A38', '\u0A39') ||
            inRange(c, '\u0A59', '\u0A5C') || inRange(c, '\u0A5E', '\u0A5E') ||
            inRange(c, '\u0A72', '\u0A74') || inRange(c, '\u0A85', '\u0A8B') ||
            inRange(c, '\u0A8D', '\u0A8D') || inRange(c, '\u0A8F', '\u0A91') ||
            inRange(c, '\u0A93', '\u0AA8') || inRange(c, '\u0AAA', '\u0AB0') ||
            inRange(c, '\u0AB2', '\u0AB3') || inRange(c, '\u0AB5', '\u0AB9') ||
            inRange(c, '\u0ABD', '\u0ABD') || inRange(c, '\u0AE0', '\u0AE0') ||
            inRange(c, '\u0B05', '\u0B0C') || inRange(c, '\u0B0F', '\u0B10') ||
            inRange(c, '\u0B13', '\u0B28') || inRange(c, '\u0B2A', '\u0B30') ||
            inRange(c, '\u0B32', '\u0B33') || inRange(c, '\u0B36', '\u0B39') ||
            inRange(c, '\u0B3D', '\u0B3D') || inRange(c, '\u0B5C', '\u0B5D') ||
            inRange(c, '\u0B5F', '\u0B61') || inRange(c, '\u0B85', '\u0B8A') ||
            inRange(c, '\u0B8E', '\u0B90') || inRange(c, '\u0B92', '\u0B95') ||
            inRange(c, '\u0B99', '\u0B9A') || inRange(c, '\u0B9C', '\u0B9C') ||
            inRange(c, '\u0B9E', '\u0B9F') || inRange(c, '\u0BA3', '\u0BA4') ||
            inRange(c, '\u0BA8', '\u0BAA') || inRange(c, '\u0BAE', '\u0BB5') ||
            inRange(c, '\u0BB7', '\u0BB9') || inRange(c, '\u0C05', '\u0C0C') ||
            inRange(c, '\u0C0E', '\u0C10') || inRange(c, '\u0C12', '\u0C28') ||
            inRange(c, '\u0C2A', '\u0C33') || inRange(c, '\u0C35', '\u0C39') ||
            inRange(c, '\u0C60', '\u0C61') || inRange(c, '\u0C85', '\u0C8C') ||
            inRange(c, '\u0C8E', '\u0C90') || inRange(c, '\u0C92', '\u0CA8') ||
            inRange(c, '\u0CAA', '\u0CB3') || inRange(c, '\u0CB5', '\u0CB9') ||
            inRange(c, '\u0CDE', '\u0CDE') || inRange(c, '\u0CE0', '\u0CE1') ||
            inRange(c, '\u0D05', '\u0D0C') || inRange(c, '\u0D0E', '\u0D10') ||
            inRange(c, '\u0D12', '\u0D28') || inRange(c, '\u0D2A', '\u0D39') ||
            inRange(c, '\u0D60', '\u0D61') || inRange(c, '\u0E01', '\u0E2E') ||
            inRange(c, '\u0E30', '\u0E30') || inRange(c, '\u0E32', '\u0E33') ||
            inRange(c, '\u0E40', '\u0E45') || inRange(c, '\u0E81', '\u0E82') ||
            inRange(c, '\u0E84', '\u0E84') || inRange(c, '\u0E87', '\u0E88') ||
            inRange(c, '\u0E8A', '\u0E8A') || inRange(c, '\u0E8D', '\u0E8D') ||
            inRange(c, '\u0E94', '\u0E97') || inRange(c, '\u0E99', '\u0E9F') ||
            inRange(c, '\u0EA1', '\u0EA3') || inRange(c, '\u0EA5', '\u0EA5') ||
            inRange(c, '\u0EA7', '\u0EA7') || inRange(c, '\u0EAA', '\u0EAB') ||
            inRange(c, '\u0EAD', '\u0EAE') || inRange(c, '\u0EB0', '\u0EB0') ||
            inRange(c, '\u0EB2', '\u0EB3') || inRange(c, '\u0EBD', '\u0EBD') ||
            inRange(c, '\u0EC0', '\u0EC4') || inRange(c, '\u0F40', '\u0F47') ||
            inRange(c, '\u0F49', '\u0F69') || inRange(c, '\u10A0', '\u10C5') ||
            inRange(c, '\u10D0', '\u10F6') || inRange(c, '\u1100', '\u1100') ||
            inRange(c, '\u1102', '\u1103') || inRange(c, '\u1105', '\u1107') ||
            inRange(c, '\u1109', '\u1109') || inRange(c, '\u110B', '\u110C') ||
            inRange(c, '\u110E', '\u1112') || inRange(c, '\u113C', '\u113C') ||
            inRange(c, '\u113E', '\u113E') || inRange(c, '\u1140', '\u1140') ||
            inRange(c, '\u114C', '\u114C') || inRange(c, '\u114E', '\u114E') ||
            inRange(c, '\u1150', '\u1150') || inRange(c, '\u1154', '\u1155') ||
            inRange(c, '\u1159', '\u1159') || inRange(c, '\u115F', '\u1161') ||
            inRange(c, '\u1163', '\u1163') || inRange(c, '\u1165', '\u1165') ||
            inRange(c, '\u1167', '\u1167') || inRange(c, '\u1169', '\u1169') ||
            inRange(c, '\u116D', '\u116E') || inRange(c, '\u1172', '\u1173') ||
            inRange(c, '\u1175', '\u1175') || inRange(c, '\u119E', '\u119E') ||
            inRange(c, '\u11A8', '\u11A8') || inRange(c, '\u11AB', '\u11AB') ||
            inRange(c, '\u11AE', '\u11AF') || inRange(c, '\u11B7', '\u11B8') ||
            inRange(c, '\u11BA', '\u11BA') || inRange(c, '\u11BC', '\u11C2') ||
            inRange(c, '\u11EB', '\u11EB') || inRange(c, '\u11F0', '\u11F0') ||
            inRange(c, '\u11F9', '\u11F9') || inRange(c, '\u1E00', '\u1E9B') ||
            inRange(c, '\u1EA0', '\u1EF9') || inRange(c, '\u1F00', '\u1F15') ||
            inRange(c, '\u1F18', '\u1F1D') || inRange(c, '\u1F20', '\u1F45') ||
            inRange(c, '\u1F48', '\u1F4D') || inRange(c, '\u1F50', '\u1F57') ||
            inRange(c, '\u1F59', '\u1F59') || inRange(c, '\u1F5B', '\u1F5B') ||
            inRange(c, '\u1F5D', '\u1F5D') || inRange(c, '\u1F5F', '\u1F7D') ||
            inRange(c, '\u1F80', '\u1FB4') || inRange(c, '\u1FB6', '\u1FBC') ||
            inRange(c, '\u1FBE', '\u1FBE') || inRange(c, '\u1FC2', '\u1FC4') ||
            inRange(c, '\u1FC6', '\u1FCC') || inRange(c, '\u1FD0', '\u1FD3') ||
            inRange(c, '\u1FD6', '\u1FDB') || inRange(c, '\u1FE0', '\u1FEC') ||
            inRange(c, '\u1FF2', '\u1FF4') || inRange(c, '\u1FF6', '\u1FFC') ||
            inRange(c, '\u2126', '\u2126') || inRange(c, '\u212A', '\u212B') ||
            inRange(c, '\u212E', '\u212E') || inRange(c, '\u2180', '\u2182') ||
            inRange(c, '\u3041', '\u3094') || inRange(c, '\u30A1', '\u30FA') ||
            inRange(c, '\u3105', '\u312C') || inRange(c, '\uAC00', '\uD7A3');
  }

  private static boolean isIdeographic(char c) {
    return inRange(c, '\u4E00', '\u9FA5') || inRange(c, '\u3007', '\u3007') ||
            inRange(c, '\u3021', '\u3029');
  }

  public static boolean isLetter(char c) {
    return isBaseChar(c) || isIdeographic(c);
  }

  public static boolean isDigit(char c) {
    return inRange(c, '\u0030', '\u0039') || inRange(c, '\u0660', '\u0669') ||
            inRange(c, '\u06F0', '\u06F9') || inRange(c, '\u0966', '\u096F') ||
            inRange(c, '\u09E6', '\u09EF') || inRange(c, '\u0A66', '\u0A6F') ||
            inRange(c, '\u0AE6', '\u0AEF') || inRange(c, '\u0B66', '\u0B6F') ||
            inRange(c, '\u0BE7', '\u0BEF') || inRange(c, '\u0C66', '\u0C6F') ||
            inRange(c, '\u0CE6', '\u0CEF') || inRange(c, '\u0D66', '\u0D6F') ||
            inRange(c, '\u0E50', '\u0E59') || inRange(c, '\u0ED0', '\u0ED9') ||
            inRange(c, '\u0F20', '\u0F29');
  }

  public static boolean isCombiningChar(char c) {
    return inRange(c, '\u0300', '\u0345') || inRange(c, '\u0360', '\u0361') ||
            inRange(c, '\u0483', '\u0486') || inRange(c, '\u0591', '\u05A1') ||
            inRange(c, '\u05A3', '\u05B9') || inRange(c, '\u05BB', '\u05BD') ||
            inRange(c, '\u05BF', '\u05BF') || inRange(c, '\u05C1', '\u05C2') ||
            inRange(c, '\u05C4', '\u05C4') || inRange(c, '\u064B', '\u0652') ||
            inRange(c, '\u0670', '\u0670') || inRange(c, '\u06D6', '\u06DC') ||
            inRange(c, '\u06DD', '\u06DF') || inRange(c, '\u06E0', '\u06E4') ||
            inRange(c, '\u06E7', '\u06E8') || inRange(c, '\u06EA', '\u06ED') ||
            inRange(c, '\u0901', '\u0903') || inRange(c, '\u093C', '\u093C') ||
            inRange(c, '\u093E', '\u094C') || inRange(c, '\u094D', '\u094D') ||
            inRange(c, '\u0951', '\u0954') || inRange(c, '\u0962', '\u0963') ||
            inRange(c, '\u0981', '\u0983') || inRange(c, '\u09BC', '\u09BC') ||
            inRange(c, '\u09BE', '\u09BE') || inRange(c, '\u09BF', '\u09BF') ||
            inRange(c, '\u09C0', '\u09C4') || inRange(c, '\u09C7', '\u09C8') ||
            inRange(c, '\u09CB', '\u09CD') || inRange(c, '\u09D7', '\u09D7') ||
            inRange(c, '\u09E2', '\u09E3') || inRange(c, '\u0A02', '\u0A02') ||
            inRange(c, '\u0A3C', '\u0A3C') || inRange(c, '\u0A3E', '\u0A3E') ||
            inRange(c, '\u0A3F', '\u0A3F') || inRange(c, '\u0A40', '\u0A42') ||
            inRange(c, '\u0A47', '\u0A48') || inRange(c, '\u0A4B', '\u0A4D') ||
            inRange(c, '\u0A70', '\u0A71') || inRange(c, '\u0A81', '\u0A83') ||
            inRange(c, '\u0ABC', '\u0ABC') || inRange(c, '\u0ABE', '\u0AC5') ||
            inRange(c, '\u0AC7', '\u0AC9') || inRange(c, '\u0ACB', '\u0ACD') ||
            inRange(c, '\u0B01', '\u0B03') || inRange(c, '\u0B3C', '\u0B3C') ||
            inRange(c, '\u0B3E', '\u0B43') || inRange(c, '\u0B47', '\u0B48') ||
            inRange(c, '\u0B4B', '\u0B4D') || inRange(c, '\u0B56', '\u0B57') ||
            inRange(c, '\u0B82', '\u0B83') || inRange(c, '\u0BBE', '\u0BC2') ||
            inRange(c, '\u0BC6', '\u0BC8') || inRange(c, '\u0BCA', '\u0BCD') ||
            inRange(c, '\u0BD7', '\u0BD7') || inRange(c, '\u0C01', '\u0C03') ||
            inRange(c, '\u0C3E', '\u0C44') || inRange(c, '\u0C46', '\u0C48') ||
            inRange(c, '\u0C4A', '\u0C4D') || inRange(c, '\u0C55', '\u0C56') ||
            inRange(c, '\u0C82', '\u0C83') || inRange(c, '\u0CBE', '\u0CC4') ||
            inRange(c, '\u0CC6', '\u0CC8') || inRange(c, '\u0CCA', '\u0CCD') ||
            inRange(c, '\u0CD5', '\u0CD6') || inRange(c, '\u0D02', '\u0D03') ||
            inRange(c, '\u0D3E', '\u0D43') || inRange(c, '\u0D46', '\u0D48') ||
            inRange(c, '\u0D4A', '\u0D4D') || inRange(c, '\u0D57', '\u0D57') ||
            inRange(c, '\u0E31', '\u0E31') || inRange(c, '\u0E34', '\u0E3A') ||
            inRange(c, '\u0E47', '\u0E4E') || inRange(c, '\u0EB1', '\u0EB1') ||
            inRange(c, '\u0EB4', '\u0EB9') || inRange(c, '\u0EBB', '\u0EBC') ||
            inRange(c, '\u0EC8', '\u0ECD') || inRange(c, '\u0F18', '\u0F19') ||
            inRange(c, '\u0F35', '\u0F35') || inRange(c, '\u0F37', '\u0F37') ||
            inRange(c, '\u0F39', '\u0F39') || inRange(c, '\u0F3E', '\u0F3E') ||
            inRange(c, '\u0F3F', '\u0F3F') || inRange(c, '\u0F71', '\u0F84') ||
            inRange(c, '\u0F86', '\u0F8B') || inRange(c, '\u0F90', '\u0F95') ||
            inRange(c, '\u0F97', '\u0F97') || inRange(c, '\u0F99', '\u0FAD') ||
            inRange(c, '\u0FB1', '\u0FB7') || inRange(c, '\u0FB9', '\u0FB9') ||
            inRange(c, '\u20D0', '\u20DC') || inRange(c, '\u20E1', '\u20E1') ||
            inRange(c, '\u302A', '\u302F') || inRange(c, '\u3099', '\u3099') ||
            inRange(c, '\u309A', '\u309A');
  }

  public static boolean isExtender(char c) {
    return inRange(c, '\u00B7', '\u00B7') || inRange(c, '\u02D0', '\u02D0') ||
            inRange(c, '\u02D1', '\u02D1') || inRange(c, '\u0387', '\u0387') ||
            inRange(c, '\u0640', '\u0640') || inRange(c, '\u0E46', '\u0E46') ||
            inRange(c, '\u0EC6', '\u0EC6') || inRange(c, '\u3005', '\u3005') ||
            inRange(c, '\u3031', '\u3035') || inRange(c, '\u309D', '\u309E') ||
            inRange(c, '\u30FC', '\u30FE');
  }


}
